<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <ul>
        <li>111111111</li>
        <li>111111111</li>
        <li>111111111</li>
        <li>111111111</li>
        <li>111111111</li>
    </ul>
</body>

</html>
<script>
    //一.函数对象的属性和方法
    // 1.属性 - length(表示参数的长度)
    // console.log(function fn(a, b, c) {}.length); //3

    // 2.函数下面的三个方法(call/apply/bind) - 改变this指向。
    // 梳理指向
    // 普通函数，自执行函数，函数表达式，回调函数 - 指向window
    // 对象方法中的函数，事件处理函数 - 指向当前的对象。
    // 构造函数 - 指向new出来的实例对象。


    // apply 、 call 、bind 三者都是用来改变函数的this对象的指向的；第一个参数都是this要指向的对象，也就是想指定的上下文；从第二个参数开始，就是函数的本身的参数；
    // var obj = {
    //     a: 1
    // }

    // function fn(n1, n2) {
    //     console.log(n1 + n2);
    //     console.log(this);
    // }
    // call:第一个参数都是this要指向的对象,从第二个参数开始，就是函数的本身的参数,多个逗号隔开
    // fn.call(obj, 3, 5);

    // apply:第一个参数都是this要指向的对象,第二个参数是数组，数组项就是函数本身的参数。
    // fn.apply(obj, [3, 5]);

    // bind:第一个参数都是this要指向的对象,从第二个参数开始，就是函数的本身的参数,多个逗号隔开,返回函数体,需要再次触发。
    // fn.bind(obj, 3, 5)();


    //应用：
    //给5个li元素添加点击事件，延迟2s将li里面的内容全部变成222222222222222222
    // var aLi = document.querySelectorAll('ul li');
    // for (var i = 0; i < aLi.length; i++) {
    //     aLi[i].onclick = function() {
    //         //this:当前点击的li
    //         window.setTimeout(function() {
    //             //this:window
    //             this.innerHTML = '2222222222222222222222222';
    //         }.bind(this), 2000); //此种情况必须使用bind，call和apply都不行。
    //     };
    // }


    //将正确的this的存储下来
    var aLi = document.querySelectorAll('ul li');
    for (var i = 0; i < aLi.length; i++) {
        aLi[i].onclick = function() {
            //this:当前点击的li
            var _this = this; //将正确的this的存储下来
            window.setTimeout(function() {
                //this:window
                _this.innerHTML = '2222222222222222222222222';
            }, 2000);
        };
    }


    // 构造函数的this指向类创建出来的对象(实例对象)
    function Fn() {
        alert(this);
    }
    Fn() //window
    new Fn(); //[object Object] 指向类创建出来的对象(实例对象)
    var f1 = new Fn(); //Fn:类，构造函数   f1:实例对象
    var f2 = new Fn(); //Fn:类，构造函数   f2:实例对象
</script>